package riteh.eventNetwork.client;

import com.google.gson.Gson;
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.Toast;
import android.view.View.OnClickListener;

public class ActivityCircles extends ExpandableListActivity {

	private static final int TYPE_CIRCLE = ExpandableListView.PACKED_POSITION_TYPE_GROUP;
	private static final int TYPE_USER = ExpandableListView.PACKED_POSITION_TYPE_CHILD;
    
	private ExpandableListView list;
	private CirclesAdapter listAdapter;
	private Button btnSearch;
	private EditText editSearch;

	private String circles[][];
	private boolean selCircles[];
	private int numOfSelCircles = 0;
	private int usersInCircle[];

	private String users[][][];
	private String usersUnformated[][];
	//private boolean selUsers[];
	//private int numOfSelUsers = 0;
	//private String usersNoRepeat[][];

	private long userId;
	private Intent intentCircleEdit, intentSeeProfile, intentSearch, intentNotifications, intentSettings, intentAbout;
	private Gson gson;

/* ********************** OVERRIDE FUNCTIONS ******************************/	
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(C.TAG, "CIRCLES Activity");
		setContentView(R.layout.circles);
		
	// INSTANCIRANJE OBJEKTA
		btnSearch = (Button) findViewById(R.id.circlesButtonSearch);
		editSearch = (EditText) findViewById(R.id.circlesEditSearch);
		list = getExpandableListView();
		intentCircleEdit = new Intent(this, ActivityCircleEdit.class);
		intentSeeProfile = new Intent(this, ActivityUserEdit.class);
		intentSearch = new Intent(this, ActivitySearch.class);
		intentNotifications = new Intent(this, ActivityNotifications.class);
		intentNotifications.putExtra("userId", userId);
        intentSettings = new Intent(this, ActivitySettings.class);
        intentAbout = new Intent(this, ActivityAbout.class);

		gson = new Gson();
		
	// AKCIJE NA STARTU
		userId = this.getIntent().getExtras().getLong("userId");
		
		refresh();
		
		registerForContextMenu(list);
		
	// EVENT LISTENERS
		
		btnSearch.setOnClickListener( new OnClickListener() {
			public void onClick(View v) {
				searchUsers(editSearch.getText().toString());
			}
		});
		
	}

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

    	MenuInflater inflater = new MenuInflater(this);
    	ExpandableListView.ExpandableListContextMenuInfo info =
    			(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
    	int type = ExpandableListView.getPackedPositionType(info.packedPosition);
    	int circlePos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
    	int userPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
    	
        if (type == TYPE_CIRCLE) {
        	if (circles[circlePos][1].compareTo("Not in any circle") == 0);
        	else if (circles[circlePos][1].compareTo("Sent requests") == 0);
        	else if (circles[circlePos][1].compareTo("Recieved requests") == 0);
        	else inflater.inflate(R.menu.long_click_circle, menu);
        }
        else if (type == TYPE_USER) {
        	if (listAdapter.getChildId(circlePos,userPos) == 0);
        	else if (circles[circlePos][1].compareTo("Recieved requests") == 0) {
        		inflater.inflate(R.menu.long_click_user_recieved, menu);
        	}
        	else if (circles[circlePos][1].compareTo("Sent requests") == 0) {
        		inflater.inflate(R.menu.long_click_user_sent, menu);
        	}
        	else inflater.inflate(R.menu.long_click_user, menu);
        }
        else {
        	menu.add("Error! tp: " + type + ", gr: " + circlePos + ", ch: " + userPos);
        }
    }
    
    public boolean onContextItemSelected(MenuItem item) {
        ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
        int type = ExpandableListView.getPackedPositionType(info.packedPosition);

        String selectionIdString;
        long selectionId;  
                
        if (type == TYPE_CIRCLE) {
        	selectionIdString = (String) info.targetView.getTag(R.id.selectionIdCircle);
        	selectionId = Long.parseLong(selectionIdString);

        	switch (item.getItemId()) {
        	case R.id.longClickCircleManageUsers:
        		circleManageUsers(selectionId);
        		return true;
        	case R.id.longClickCircleEdit:
        		circleEdit(selectionId);
        		return true;
        	case R.id.longClickCircleDelete:
            	circleDelete(selectionId);
        		return true;
        	}
        }
        else if (type == TYPE_USER) {
        	selectionIdString = (String) info.targetView.getTag(R.id.selectionIdUser);
        	selectionId = Long.parseLong(selectionIdString);
           
        	switch (item.getItemId()) {
        	case R.id.longClickUserSeeProfile:
        		userSeeProfile(selectionId);
        		return true;
        	case R.id.longClickUserManageCircles:
        	case R.id.longClickUserRecievedAccept:
        		userManageCircles(selectionId);
        		return true;
        	case R.id.longClickUserUnfriend:
        	case R.id.longClickUserRecievedRemove:
        	case R.id.longClickUserSentRemove:
        		userUnfriend(selectionId);
        		return true;
        	}
        }
        return false;
    }
    
    public boolean onCreateOptionsMenu(Menu menu) {
    	super.onCreateOptionsMenu(menu);
    	MenuInflater inflater = new MenuInflater(this);
    	inflater.inflate(R.menu.circles, menu);
    	return true;
    }
    
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
    	case R.id.circlesMenuCreateCircle:
    		createCircle();
    		return true;
    	case R.id.circlesMenuSettings:
    		showSettings();
    		return true;
    	case R.id.circlesMenuRefresh:
    		refresh();
    		return true;
    	case R.id.circlesMenuAbout:
    		startActivity(intentAbout);
    		return true;
    	}
    	return false;
    }
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	super.onActivityResult(requestCode, resultCode, data);
    	Log.d(C.TAG,"CIRCLES: onActivityResult: request: " + requestCode + ", result: " + resultCode);

    	switch (requestCode) {
    	case C.ACTIVITY_CIRCLE_EDIT:
    		if (resultCode == -1) return;
    		else getCirclesAndUsers();
    		return;
    	case C.ACTIVITY_SEARCH:
    		if (resultCode == -1) return;
    		else getCirclesAndUsers();
    		return;
    	case C.ACTIVITY_USER_EDIT:
    		return;
    	}
    }

/* ********************** PRIVATE FUNCTIONS *******************************/
    
	private void refresh() {
		int numOfNotifications;
		numOfNotifications = getNumberOfNotifications();
		
		if (numOfNotifications > 0) {
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage("You have " + numOfNotifications + " new notifications!")
			       .setCancelable(false)
			       .setPositiveButton("Show", new DialogInterface.OnClickListener() {
			           public void onClick(DialogInterface dialog, int id) {
			        	   startActivity(intentNotifications);
			           }
			       })
			       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			           public void onClick(DialogInterface dialog, int id) {
			                dialog.cancel();
			           }
			       });
			AlertDialog alert = builder.create();
			alert.show();
		}
		
		getCirclesAndUsers();
	}
	
	private int getNumberOfNotifications() {
	 	Log.d(C.TAG, "PROFILE: getNumberOfNotification()");
	
	 	RestClient client = new RestClient(getString(R.string.serverMethodGetNumberOfNotifications));
		client.AddParam("userId", String.valueOf(userId));
	 	
	 	String result = C.getMethod0(client, getString(R.string.serverMethodGetNumberOfNotifications));
	 	if (C.resultSuccess(this, result, getString(R.string.toastGetNumberOfNotificationsError))) {
	 		return Integer.parseInt(result);
	 	}
	 	else return 0;
	}
    
	private void showSettings() {
    	startActivity(intentSettings);
    }
    
    private void searchUsers(String query) {
    	if (query.isEmpty()) {
    		C.toast(this, "Enter search keyword!");
    		return;
    	}
		intentSearch.putExtra("query", query);
		intentSearch.putExtra("userId", userId);
		startActivityForResult(intentSearch, C.ACTIVITY_SEARCH);
    }
    
    private void createCircle() {
		intentCircleEdit.putExtra("userId", userId);
		intentCircleEdit.putExtra("circleId", 0);
		startActivityForResult(intentCircleEdit,C.ACTIVITY_CIRCLE_EDIT);
    }
    
    private void userSeeProfile(long userInfoId) {
		intentSeeProfile.putExtra("userId", userId);
		intentSeeProfile.putExtra("userInfoId", userInfoId);
		startActivityForResult(intentSeeProfile, C.ACTIVITY_USER_EDIT);
    }
    
    private void userManageCircles(long userInfoId) {
    	Log.d(C.TAG, "CIRCLES: userManageCircles()");
		final CharSequence[] items;
		final long selectedUserId = userInfoId;
		
		items = new CharSequence[circles.length];
		for (int i=0; i<circles.length; i++) items[i] = circles[i][1];
		
		fillSelCircles(userInfoId);
		
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("Select circles for this user: ");
		builder.setNeutralButton("Save changes", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				userManageCirclesExec(selectedUserId);
			}
		});
		
		builder.setMultiChoiceItems(items, selCircles,  new OnMultiChoiceClickListener() {
			public void onClick(DialogInterface dialog, int which, boolean isChecked) {
				selCircles[which] = isChecked;
				if (isChecked) numOfSelCircles++;
				else numOfSelCircles--;
			}
		});
		
		AlertDialog alert = builder.create();
		alert.show();
    }
    
    private void fillSelCircles(long id) {
    	for (int i=0; i<users.length; i++) {
    		selCircles[i] = false;
    		for (int j=0; j<usersInCircle[i]; j++) {
    			if (Long.parseLong(users[i][j][0]) == id) {
    				selCircles[i]=true;
    				numOfSelCircles++;
    				break;
    			}
    		}
    	}
    }
    
    private void userManageCirclesExec(long selectedUserId) {
    	
    	// Find id's of selected circles
    	String selCirclesId[] = new String[numOfSelCircles];
    	int tmp=0; 
    	boolean acceptFriend = false;
    	for(int i=0; i<circles.length; i++) {
    		if (selCircles[i]) {
    			selCirclesId[tmp] = circles[i][0];
    			tmp++;
    		}
    	}
    	
    	// Find id of recived friedship request circle
    	long recivedRequestsCircleId = 0;
    	for (int i=0; i<circles.length; i++) {
    		if (circles[i][1].compareTo("Recieved requests") == 0) {
    			recivedRequestsCircleId = Long.parseLong(circles[i][0]);
    		}
    	}
    	Log.d(C.TAG, "recivedRequestCircleId=" + recivedRequestsCircleId);
    	
    	// Find if user is in recived frienship request circle
    	for (int i=0; i<usersUnformated.length; i++) {
    		if (Long.parseLong(usersUnformated[i][0]) == selectedUserId) {
    			if (Long.parseLong(usersUnformated[i][1]) == recivedRequestsCircleId ) {
    				acceptFriend = true;
    			}
    		}
    	}
    	
    	RestClient client = new RestClient(getString(R.string.serverMethodUserManageCircles));
    	if (acceptFriend) {
    		client = new RestClient(getString(R.string.serverMethodAcceptFriendship));
    	}
    	
    	client.AddParam("userId", String.valueOf(userId));
    	client.AddParam("selectedUserId", String.valueOf(selectedUserId));
    	client.AddParam("circles", gson.toJson(selCirclesId));
    	
    	String result;
    	
    	if (acceptFriend) {
    		result = C.getMethod0(client, getString(R.string.serverMethodAcceptFriendship));
    	}
    	else {
    		result = C.getMethod0(client, getString(R.string.serverMethodUserManageCircles));
    	}
    	
    	if (C.resultSuccess(this, result, getString(R.string.toastUserManageCirclesError))) {
    		getCirclesAndUsers();
    	}
    }
    
    private void userUnfriend(long userInfoId) {
    	Log.d(C.TAG, "CIRCLES: userUnfriend()");
    	RestClient client = new RestClient(getString(R.string.serverMethodUserUnfriend));
    	client.AddParam("userId", String.valueOf(userId));
    	client.AddParam("selectedUserId", String.valueOf(userInfoId));
    
    	String result = C.getMethod0(client, getString(R.string.serverMethodUserUnfriend));
    	
    	if (C.resultSuccess(this, result, getString(R.string.toastRemoveFriendshipError))) {
    		C.toast(this, "You are no longer friends!", Toast.LENGTH_SHORT);
    		getCirclesAndUsers();
    	}
    }
    
    // TODO circleManageUsers()
    private void circleManageUsers(long circleId) {
    	/*Log.d(C.TAG, "CIRCLES: circleManageUsers()");
		final CharSequence[] items;
		final long selCircleId = circleId;
		int addedUsers = 0;
		
		items = new CharSequence[usersUnformated.length];
		
		for (int i=0; i<usersUnformated.length; i++) {
			for (int j=0; j<addedUsers; j++) {
				if (items[j].toString().compareTo(usersUnformated[i][]) == 0) {
					
				}
			}
			items[i] = circles[i][1];
		}
		
		fillSelCircles(userInfoId);
		*/
		/*
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("Select circles for this user: ");
		builder.setNeutralButton("Save changes", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				userManageCirclesExec(selectedUserId);
			}
		});
		
		builder.setMultiChoiceItems(items, selCircles,  new OnMultiChoiceClickListener() {
			public void onClick(DialogInterface dialog, int which, boolean isChecked) {
				selCircles[which] = isChecked;
				if (isChecked) numOfSelCircles++;
				else numOfSelCircles--;
			}
		});
		
		AlertDialog alert = builder.create();
		alert.show();*/
    }
    
    private void circleDelete(long circleId) {
    	Log.d(C.TAG, "CIRCLES: circleDelete()");
    	RestClient client = new RestClient(getString(R.string.serverMethodDeleteCircle));
    	client.AddParam("userId", String.valueOf(userId));
    	client.AddParam("circleId", String.valueOf(circleId));
    
    	String result = C.getMethod0(client, getString(R.string.serverMethodDeleteCircle));
    	
    	if (C.resultSuccess(this,result,getString(R.string.toastDeleteCircleError))) {
    		C.toast(this, "Circle deleted!",Toast.LENGTH_SHORT);
    		getCirclesAndUsers();
    	}
    	
    }
    
    private void circleEdit(long circleId) {
    	String color="", name="";
    	for (int i=0; i<circles.length; i++) {
    		if (Long.parseLong(circles[i][0]) == circleId) {
    			name = circles[i][1];
    			color = circles[i][2];
    		}
    	}
		intentCircleEdit.putExtra("action", "edit");
		intentCircleEdit.putExtra("circleId", circleId);
		intentCircleEdit.putExtra("circleName", name);
		intentCircleEdit.putExtra("circleColor", color);
		
		startActivity(intentCircleEdit);
    }
    
    private void getCirclesAndUsers() {
    	
    	RestClient client = new RestClient(getString(R.string.serverMethodGetCircles));
    	client.AddParam("userId", String.valueOf(userId));
    	
    	String result[][] = C.getMethod2(client, getString(R.string.serverMethodGetCircles));
    	
    	
    	if (C.resultSuccess(this, result, getString(R.string.toastGetCirclesError))) {
    		circles = result;
    		selCircles = new boolean[circles.length];
    	}
    	else return;
    	
    	client = new RestClient(getString(R.string.serverMethodGetFriends));
    	client.AddParam("userId", String.valueOf(userId));

    	String result2[][] = C.getMethod2(client, getString(R.string.serverMethodGetFriends));

    	if (C.resultSuccess(this, result2, getString(R.string.toastGetFriendsError))) {
    		usersUnformated = result2;
    		formatUsersString(usersUnformated);
			listAdapter = new CirclesAdapter();
			list.setAdapter(listAdapter);
    	}

    }
    
    private void formatUsersString(String tmpUsers[][]) {
		int circleCounts[] = new int[circles.length];
		int tmp=0;
		int max=0;
		int tmpUsersLength=0;
		
		if (tmpUsers[0][0].compareTo("0") != 0) tmpUsersLength = tmpUsers.length;
		
		// Inicijaliziraj polje na 0
		for (int i=0; i<circleCounts.length; i++) circleCounts[i]=0;
		
		// Pronadji koliko ima usera u svakom krugu
		for (int i=0; i<tmpUsersLength; i++) {
			String circleId = tmpUsers[i][1];
			
			for (int j=0; j<circles.length; j++) {
				tmp=j;
				if (circleId.compareTo(circles[j][0]) == 0) break;
			}
			
			circleCounts[tmp]++;
		}

		
		// Pronadji najveci broj usera u krugu
		for (int i=0; i<circleCounts.length; i++) {
			if (circleCounts[i] > max) max=circleCounts[i];
		}
		
		// Inicijaliziraj broj usera u krugu na 0
		usersInCircle = new int[circleCounts.length];
		for (int i=0; i<max; i++) usersInCircle[i]=0;
		
		if (max == 0) max++;
		
		users = new String[circles.length][max][2];
		
		// DEBUG
		//Log.d(C.TAG, "DEBUG: tmpUsersLen=" + tmpUsersLength + ", max=" + max);
		
		for (int i=0; i<tmpUsersLength; i++) {
			int circlePos = findCirclePos(tmpUsers[i][1]);
			users[circlePos][usersInCircle[circlePos]][0] = tmpUsers[i][0];
			users[circlePos][usersInCircle[circlePos]][1] = tmpUsers[i][2] + " " + tmpUsers[i][3];
			usersInCircle[circlePos]++;
		}
		
		for (int i=0; i<users.length; i++) {
			if (usersInCircle[i] == 0) {
				users[i][0][0] = "0";
				users[i][0][1] = "Circle is empty";
				//usersInCircle[i]++;
			}
		}
	}
	
	private int findCirclePos(String id) {
		for (int i=0; i<circles.length; i++) {
			if (id.compareTo(circles[i][0]) == 0) return i;
		}
		return 1;
	}
	
	private class CirclesAdapter extends BaseExpandableListAdapter {

		public Object getChild(int groupPosition, int childPosition) {
			if (Integer.parseInt(users[groupPosition][0][0]) == 0) return "Circle is empty";
			return users[groupPosition][childPosition][1];
		}

		public long getChildId(int groupPosition, int childPosition) {
			if (Integer.parseInt(users[groupPosition][0][0]) == 0) return 0;
			return Long.parseLong(users[groupPosition][childPosition][0]);
		}
        
		public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 
				View convertView, ViewGroup parent) {
        	AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 40);
        	TextView view = new TextView(ActivityCircles.this);
        	view.setLayoutParams(lp);
        	view.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        	view.setPadding(50,0,0,0);
        	view.setTextSize(16);
        	view.setTypeface(Typeface.DEFAULT_BOLD);
			if (users[groupPosition].length <= childPosition) {
				view.setText("No users in this circle!");
			}
			else view.setText(getChild(groupPosition, childPosition).toString());
            view.setTag(R.id.selectionIdUser, users[groupPosition][childPosition][0]);
            return view;
		}

		public int getChildrenCount(int groupPosition) {
			return users[groupPosition].length;
		}

		public Object getGroup(int groupPosition) {
			return circles[groupPosition][1];
		}

		public int getGroupCount() {
			return circles.length;
		}

		public long getGroupId(int groupPosition) {
			return Long.parseLong(circles[groupPosition][0]);
		}

		public View getGroupView(int groupPosition, boolean isExpanded,
				View convertView, ViewGroup parent) {
        	AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 40);
        	TextView view = new TextView(ActivityCircles.this);
        	view.setLayoutParams(lp);
        	view.setGravity(Gravity.BOTTOM | Gravity.LEFT);
        	view.setPadding(36,0,0,3);
        	view.setTextSize(20);
            view.setTextColor(Color.parseColor(circles[groupPosition][2]));
            view.setTypeface(Typeface.DEFAULT_BOLD);
            view.setText(getGroup(groupPosition).toString());
            view.setTag(R.id.selectionIdCircle, circles[groupPosition][0]);
            return view;
		}

		public boolean hasStableIds() {
			return true;
		}

		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return true;
		}
	}
	
/*
	private class Circle {
		private String id, name, color;
		Vector<User> users;
		
		public Circle(String[] circle) {
			id = circle[0];
			name = circle[1];
			color = circle[2];
		}
		
		public void addUser(User user) {
			users.add(user);
		}
		
		public long getId() {
			return Long.parseLong(id);
		}
		
		public String getName() {
			return name;
		}
		
		public int getColor() {
			return Color.parseColor(color);
		}
		
		public int userCount() {
			return users.size();
		}
	}
	
	private class User {
		private String id, name, surname;
		
		public long getId() {
			return Long.parseLong(id);
		}
		
		public String getName() {
			return name;
		}
		
		public String getSurname() {
			return surname;
		}
		
		public String getNameAndSurname() {
			return name + " " + surname;
		}
	}
*/
}